package com.freewater.javabase.demo.crypto;

import javax.crypto.Cipher;
import java.math.BigInteger;
import java.security.*;

public class RsaCrypto {

    public static void main(String[] args) {
        try {
            // 明文:
            byte[] plain = "Hello, encrypt use RSA".getBytes("UTF-8");
            // 创建公钥／私钥对:
            Person alice = new Person("Alice");
            alice.generateKeyPair();
            // 用Alice的公钥加密:
            byte[] pk = alice.getPublicKey();
            System.out.println(String.format("public key: %x", new BigInteger(1, pk)));
            byte[] encrypted = alice.encrypt(plain);
            System.out.println(String.format("encrypted: %x", new BigInteger(1, encrypted)));
            // 用Alice的私钥解密:
            byte[] sk = alice.getPrivateKey();
            System.out.println(String.format("private key: %x", new BigInteger(1, sk)));
            byte[] decrypted = alice.decrypt(encrypted);
            System.out.println(new String(decrypted, "UTF-8"));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static class Person {
        public final String name;
        public PublicKey publicKey;
        public PrivateKey privateKey;

        Person(String name) {
            this.name = name;
        }

        void generateKeyPair() throws NoSuchAlgorithmException {
            KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
            keyPairGenerator.initialize(1024);
            KeyPair keyPair = keyPairGenerator.generateKeyPair();
            this.publicKey = keyPair.getPublic();
            this.privateKey = keyPair.getPrivate();
        }

        public byte[] getPrivateKey() {
            return this.privateKey.getEncoded();
        }

        public byte[] getPublicKey() {
            return this.publicKey.getEncoded();
        }

        // 用公匙加密
        public byte[] encrypt(byte[] input) throws Exception {
            Cipher cipher = Cipher.getInstance("RSA");
            cipher.init(Cipher.ENCRYPT_MODE, this.publicKey);
            byte[] encrypted = cipher.doFinal(input);
            return encrypted;
        }

        // 用私匙解密
        public byte[] decrypt(byte[] input) throws Exception {
            Cipher cipher = Cipher.getInstance("RSA");
            cipher.init(Cipher.DECRYPT_MODE, this.privateKey);
            byte[] decrypted = cipher.doFinal(input);
            return decrypted;
        }
    }
}
